package com.personal.system.controller.act;

import cn.hutool.core.util.StrUtil;
import com.personal.common.result.Result;
import com.personal.system.entity.FormData;
import com.personal.system.entity.ProcessDefinitionDTO;
import com.personal.system.entity.WorkflowExample;
import com.personal.system.mapper.act.FormDataMapper;
import com.personal.system.service.act.WorkflowExampleService;
import com.personal.system.config.SecurityUtil;
import com.personal.system.utils.UUID;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;


@RestController
@RequestMapping("/act/processDefinition")
public class ProcessDefinitionController {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private ProcessRuntime processRuntime;

    @Resource
    private FormDataMapper formDataMapper;

    @Resource
    private WorkflowExampleService exampleService;

    @Resource
    private SecurityUtil securityUtil;


    @PostMapping(value = "/uploadStreamAndDeployment")
    public Result uploadStreamAndDeployment(@RequestParam("file") MultipartFile file) {
        // 获取上传的文件名
        String fileName = file.getOriginalFilename();

        try {
            // 得到输入流（字节流）对象
            InputStream fileInputStream = file.getInputStream();

            // 文件的扩展名
            String extension = FilenameUtils.getExtension(fileName);

            // ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//创建处理引擎实例
            // repositoryService = processEngine.getRepositoryService();//创建仓库服务实例

            Deployment deployment = null;
            if (extension.equals("zip")) {
                ZipInputStream zip = new ZipInputStream(fileInputStream);
                deployment = repositoryService.createDeployment()//初始化流程
                        .addZipInputStream(zip)
                        .name(fileName)
                        .deploy();
            } else {
                deployment = repositoryService.createDeployment()//初始化流程
                        .addInputStream(fileName, fileInputStream)
                        .name(fileName)
                        .deploy();
            }

            return Result.ok(deployment.getId() + "-" + fileName);

        } catch (Exception e) {
            return Result.fail().message("部署流程失败");
        }

    }


    @PostMapping(value = "/upload")
    public Result upload(HttpServletRequest request, @RequestParam("processFile") MultipartFile multipartFile) {

        if (multipartFile.isEmpty()) {
            return Result.fail("文件为空");
        }
        String fileName = multipartFile.getOriginalFilename();  // 文件名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));  // 后缀名
        String filePath = "D:\\360Downloads\\"; // 上传后的路径

        //本地路径格式转上传路径格式
        filePath = filePath.replace("\\", "/");
        filePath = filePath.replace("file:", "");

        // String filePath = request.getSession().getServletContext().getRealPath("/") + "bpmn/";
        fileName = UUID.randomUUID() + suffixName; // 新文件名
        File file = new File(filePath + fileName);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            multipartFile.transferTo(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.ok("/profile/" + fileName);
    }

    //
//
//    /**
//     *
//     * @param deploymentFileUUID
//     * @return
//     */
//    @PostMapping(value = "/addDeploymentByFileNameBPMN")
//    public AjaxResponse addDeploymentByFileNameBPMN(@RequestParam("deploymentFileUUID") String deploymentFileUUID, @RequestParam("deploymentName") String deploymentName) {
//        try {
//            String filename = "resources/bpmn/" + deploymentFileUUID;
//            Deployment deployment = repositoryService.createDeployment()//初始化流程
//                    .addClasspathResource(filename)
//                    .name(deploymentName)
//                    .deploy();
//            //System.out.println(deployment.getName());
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
//                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId());
//        } catch (Exception e) {
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
//                    "BPMN部署流程失败", e.toString());
//        }
//
//    }
//
    @PostMapping(value = "/addDeploymentByString")
    public Result addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN) {
        try {
            String[] split = stringBPMN.split("<");
            String one = "";
            for (String str : split) {
                if (StrUtil.isNotBlank(one)) continue;
                if (str.contains("name")) one = str;
            }

            String[] kong = one.split(" ");
            String name = "";
            for (String str : kong) {
                if (str.contains("name")) name = str.replace("\"", "").split("=")[1];
            }

            Deployment deployment = repositoryService.createDeployment()
                    .addString(name + ".bpmn", stringBPMN)
                    .name(name)
                    .deploy();
            return Result.ok(deployment.getId());
        } catch (Exception e) {
            return Result.fail().message("string部署流程失败");
        }
    }

//缺失流程部署ID属性版本，import org.activiti.api.process.model.ProcessDefinition;
    /*@GetMapping(value = "/getDefinitions")
    public AjaxResponse getDefinitions() {

        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("wukong");
            }
            Page<ProcessDefinition> processDefinitions = processRuntime.processDefinitions(Pageable.of(0, 50));
            System.out.println("流程定义数量： " + processDefinitions.getTotalItems());
            for (ProcessDefinition pd : processDefinitions.getContent()) {
                System.out.println("getId：" + pd.getId());
                System.out.println("getName：" + pd.getName());
                System.out.println("getStatus：" + pd.getKey());
                System.out.println("getStatus：" + pd.getFormKey());
            }


            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processDefinitions.getContent());
        }catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程定义失败", e.toString());
        }
    }*/


    //import org.activiti.engine.RepositoryService;
    @GetMapping(value = "/getDefinitions/{pageNum}/{pageSize}")
    public Result getDefinitions(@PathVariable int pageNum, @PathVariable int pageSize
            , ProcessDefinitionDTO definitionDTO) {

        try {
            List<HashMap<String, Object>> listMap = new ArrayList<>();
//            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

            ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
                    .orderByProcessDefinitionId()
                    .orderByProcessDefinitionVersion().desc();
            if (StrUtil.isNotBlank(definitionDTO.getName())) {
                query.processDefinitionNameLike("%" + definitionDTO.getName() + "%");
            }
            if (StrUtil.isNotBlank(definitionDTO.getKey())) {
                query.processDefinitionKeyLike("%" + definitionDTO.getKey() + "%");
            }
            List<ProcessDefinition> list = query.listPage(pageNum - 1, pageSize);

            for (ProcessDefinition pd : list) {
                HashMap<String, Object> hashMap = new HashMap<>();
                //System.out.println("流程定义ID："+pd.getId());
                hashMap.put("processDefinitionId", pd.getId());
                hashMap.put("name", pd.getName());
                hashMap.put("key", pd.getKey());
                hashMap.put("resourceName", pd.getResourceName());
                hashMap.put("deploymentId", pd.getDeploymentId());
                hashMap.put("version", pd.getVersion());
                listMap.add(hashMap);
            }

            Map<String, Object> map = new HashMap<>();
            map.put("listMap", listMap);
            map.put("total", query.count());
            return Result.ok(map);
        } catch (Exception e) {
            return Result.fail().message("获取流程定义失败");
        }
    }

    //启动流程实例
    @PostMapping(value = "/startProcess")
    public Result startProcess(@RequestBody Map<String, String> map) {
        String processDefinitionKey = map.get("processDefinitionKey");
        String instName = map.get("instName");

        WorkflowExample example = new WorkflowExample();
        String id = UUID.fastUUID().toString(true);
        example.setId(id);
        example.setCreateName(securityUtil.getUserName());
        ProcessInstance instance = processRuntime.start(
                ProcessPayloadBuilder.start()
                        .withProcessDefinitionKey(processDefinitionKey)
                        .withBusinessKey(id)
                        .withName(instName).build());
        ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(instance.getProcessDefinitionId())
                .singleResult();
        example.setInstanceId(instance.getId());
        example.setName(instance.getName());
        example.setProcessDefinitionId(instance.getProcessDefinitionId());
        example.setProcessDefinitionKey(instance.getProcessDefinitionKey());
        example.setProcessDefinitionVersion(instance.getProcessDefinitionVersion());
        example.setStatus(instance.getStatus().name());
        example.setStartDate(instance.getStartDate());
        example.setDeploymentId(pd.getDeploymentId());
        example.setResourceName(pd.getResourceName());

        exampleService.insertWorkflowExample(example);

        return Result.ok(example);
    }

    //获取流程定义XML
    @GetMapping(value = "/getDefinitionXML")
    public void getProcessDefineXML(HttpServletResponse response,
                                    @RequestParam("deploymentId") String deploymentId,
                                    @RequestParam("resourceName") String resourceName) {
        try {
            InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
            int count = inputStream.available();
            byte[] bytes = new byte[count];
            response.setContentType("text/xml");
            OutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            inputStream.close();
        } catch (Exception e) {
            e.toString();
        }
    }


    //    @GetMapping(value = "/getDeployments")
//    public AjaxResponse getDeployments() {
//        try {
//
//            List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
//            List<Deployment> list = repositoryService.createDeploymentQuery().list();
//            for (Deployment dep : list) {
//                HashMap<String, Object> hashMap = new HashMap<>();
//                hashMap.put("id", dep.getId());
//                hashMap.put("name", dep.getName());
//                hashMap.put("deploymentTime", dep.getDeploymentTime());
//                listMap.add(hashMap);
//            }
//
//
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
//                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
//        } catch (Exception e) {
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
//                    "查询失败", e.toString());
//        }
//    }
//
//
//
    //删除流程定义
    @GetMapping(value = "/delDefinition/{depID}/{pdID}")
    public Result delDefinition(@PathVariable("depID") String depID, @PathVariable("pdID") String pdID) {
        try {

            //删除数据
            formDataMapper.delete(Wrappers.lambdaQuery(FormData.class).eq(FormData::getProcDefId, pdID));
            repositoryService.deleteDeployment(depID, true);

            return Result.ok("删除成功");
        } catch (Exception e) {
            return Result.fail().message("删除失败");
        }
    }

}
